/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "secure_element_session.h"
#include "channel.h"
#include "secure_element_channel.h"
#include "secure_element_common.h"

namespace OHOS {
namespace SE {
namespace OMAPI {
void SESessionImpl::SetSession(std::shared_ptr<Session> se)
{
    session_ = se;
}

void SESessionImpl::SetReader(SEReaderImpl *rd)
{
    reader_ = rd;
}

int64_t SESessionImpl::GetReader(int32_t *errorCode)
{
    if (session_ == nullptr || reader_ == nullptr) {
        ErrorLog("SESessionImpl instance is nullptr");
        *errorCode = CJ_UNSUPPORTED_ERR;
        return CJ_INVALID_VALUE_64;
    }
    return reader_->GetID();
}

std::string SESessionImpl::GetATR(int32_t *errorCode)
{
    std::string atr = "";
    if (session_ == nullptr) {
        ErrorLog("SESessionImpl instance is nullptr");
        *errorCode = CJ_UNSUPPORTED_ERR;
        return atr;
    }
    int32_t statusCode = session_->GetATR(atr);
    if (statusCode != ErrorCode::SE_SUCCESS) {
        ErrorLog("SESessionImpl: GetATR failed");
        *errorCode = Convert2CJErrorCode(static_cast<ErrorCode>(statusCode));
        return "";
    }
    return atr;
}

void SESessionImpl::Close(int32_t *errorCode)
{
    if (session_ == nullptr) {
        ErrorLog("SESessionImpl instance is nullptr");
        *errorCode = CJ_UNSUPPORTED_ERR;
        return;
    }
    int32_t statusCode = session_->Close();
    if (statusCode != ErrorCode::SE_SUCCESS) {
        ErrorLog("SESessionImpl: Close failed");
        *errorCode = Convert2CJErrorCode(static_cast<ErrorCode>(statusCode));
    }
}

bool SESessionImpl::IsClosed(int32_t *errorCode)
{
    bool isClose = false;
    if (session_ == nullptr) {
        ErrorLog("SESessionImpl instance is nullptr");
        *errorCode = CJ_UNSUPPORTED_ERR;
        return isClose;
    }
    int32_t statusCode = session_->IsClosed(isClose);
    if (statusCode != ErrorCode::SE_SUCCESS) {
        ErrorLog("SESessionImpl: IsClosed failed");
        *errorCode = Convert2CJErrorCode(static_cast<ErrorCode>(statusCode));
        return false;
    }
    return isClose;
}

void SESessionImpl::CloseChannels(int32_t *errorCode)
{
    if (session_ == nullptr) {
        ErrorLog("SESessionImpl instance is nullptr");
        *errorCode = CJ_UNSUPPORTED_ERR;
        return ;
    }
    int32_t statusCode = session_->CloseChannels();
    if (statusCode != ErrorCode::SE_SUCCESS) {
        ErrorLog("SESessionImpl: CloseChannels failed");
        *errorCode = Convert2CJErrorCode(static_cast<ErrorCode>(statusCode));
    }
}

int64_t SESessionImpl::OpenBasicChannel(std::string aid, int32_t *errorCode)
{
    return OpenBasicChannel(aid, 0, errorCode);
}

int64_t SESessionImpl::OpenBasicChannel(std::string aid, int32_t p2, int32_t *errorCode)
{
    if (session_ == nullptr) {
        ErrorLog("SESessionImpl instance is nullptr");
        *errorCode = CJ_ILLEGAL_STATE_ERR;
        return CJ_INVALID_VALUE_64;
    }
    int32_t err = IsSupportOpenBasicChannel(session_);
    if (err != ErrorCode::SE_SUCCESS) {
        ErrorLog("SIM not support open basic channel");
        *errorCode = Convert2CJErrorCode(static_cast<ErrorCode>(err));
        return CJ_INVALID_VALUE_64;
    }
    std::string response = "";
    std::shared_ptr<Channel> channel;
    int32_t statusCode = session_->OpenBasicChannel(aid, p2, channel, response);
    if (statusCode != ErrorCode::SE_SUCCESS) {
        ErrorLog("SESessionImpl: OpenBasicChannel failed");
        *errorCode = Convert2CJErrorCode(static_cast<ErrorCode>(statusCode));
        return CJ_INVALID_VALUE_64;
    }
    auto chn = FFIData::Create<SEChannelImpl>();
    if (chn == nullptr) {
        ErrorLog("SEChannelImpl instance is nullptr");
        *errorCode = CJ_ILLEGAL_STATE_ERR;
        return CJ_INVALID_VALUE_64;
    }
    repsonse_ = response;
    chn->SetChannel(channel);
    chn->SetSession(this);
    return chn->GetID();
}

int64_t SESessionImpl::OpenLogicalChannel(std::string aid, int32_t *errorCode)
{
    return OpenLogicalChannel(aid, 0, errorCode);
}

int64_t SESessionImpl::OpenLogicalChannel(std::string aid, int32_t p2, int32_t *errorCode)
{
    if (session_ == nullptr) {
        ErrorLog("SESessionImpl instance is nullptr");
        *errorCode = CJ_ILLEGAL_STATE_ERR;
        return CJ_INVALID_VALUE_64;
    }
    std::string response = "";
    std::shared_ptr<Channel> channel;
    int32_t statusCode = session_->OpenLogicalChannel(aid, p2, channel, response);
    if (statusCode != ErrorCode::SE_SUCCESS) {
        ErrorLog("SESessionImpl: OpenLogicalChannel failed");
        *errorCode = Convert2CJErrorCode(static_cast<ErrorCode>(statusCode));
        return CJ_INVALID_VALUE_64;
    }
    auto chn = FFIData::Create<SEChannelImpl>();
    if (chn == nullptr) {
        ErrorLog("SEChannelImpl instance is nullptr");
        *errorCode = CJ_ILLEGAL_STATE_ERR;
        return CJ_INVALID_VALUE_64;
    }
    repsonse_ = response;
    chn->SetChannel(channel);
    chn->SetSession(this);
    return chn->GetID();
}
}  // namespace OMAPI
}  // namespace SE
}  // namespace OHOS